﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;

namespace DatabaseUserTest.Model
{

    public class Dijkstra
    {
        private Graph shortestpath = new Graph();
        private List<WeightedGraphEdge> heap = new List<WeightedGraphEdge>();
        private GraphNode graphnode = new GraphNode();
        private NodeAdd add = new NodeAdd();
        private List<GraphNode> nodelist = new List<GraphNode>();
        private CompleteRoute completeRoute = new CompleteRoute();
        private CompleteRoute nextestBestestRoute = new CompleteRoute();
        private CompleteRoute loserRoute = new CompleteRoute();
        private List<CompleteRoute> routers = new List<CompleteRoute>();
        private GraphNode ygogg = new GraphNode();

        public CompleteRoute FindShortestPath(GraphNode source, GraphNode end, Graph graph)
        {


            foreach (GraphNode node in graph)
            {
                node.Value = double.PositiveInfinity;
                node.SecondValue = double.PositiveInfinity;
                node.ThirdValue = double.PositiveInfinity;
            }

            source.Value = 0;
            source.SecondValue = double.PositiveInfinity;
            source.ThirdValue = double.PositiveInfinity;


            GraphNode bestnode = new GraphNode();

            bestnode.Value = double.PositiveInfinity;
            for (int j = 0; j < graph.Nodes.Count; j++)
            {

                for (int i = 0; i < source.Neighbors.Count; i++)
                {
                    WeightedGraphEdge edge = new WeightedGraphEdge(source.Costs[i], source.NodeName, source.Neighbors[i]);
                    if (edge.to.Mark == false)
                    {
                        if (edge.weight + source.Value <= edge.to.Value)
                        {
                            edge.to.ThirdValue = edge.to.SecondValue;
                            edge.to.ThirdPredecessor = edge.to.SecondPredecessor;
                            edge.to.SecondValue = edge.to.Value;
                            edge.to.SecondPredecessor = edge.to.FirstPredecessor;
                            edge.to.Value = edge.weight + source.Value;
                            edge.to.FirstPredecessor = AddToString(source.FirstPredecessor, edge.to.NodeName);

                            if (bestnode.Value > edge.to.Value)
                            {
                                bestnode = edge.to;
                            }
                        }
                        #region Extra stuff
                        //else if (edge.weight + source.Value <= edge.to.SecondValue)
                        //{
                        //    edge.to.ThirdValue = edge.to.SecondValue;
                        //    edge.to.ThirdPredecessor = edge.to.SecondPredecessor;
                        //    edge.to.SecondValue = edge.weight + source.Value;
                        //    edge.to.SecondPredecessor = AddToString(source.SecondPredecessor, edge.to.NodeName);
                        //}
                        //else if (edge.weight + source.Value <= edge.to.ThirdValue)
                        //{
                        //    edge.to.ThirdValue = edge.weight + source.Value;
                        //    edge.to.ThirdPredecessor = AddToString(source.ThirdPredecessor, edge.to.NodeName);
                        //}

                        //if (edge.weight + source.SecondValue <= edge.to.SecondValue)
                        //{
                        //    edge.to.ThirdValue = edge.to.SecondValue;
                        //    edge.to.ThirdPredecessor = edge.to.SecondPredecessor;
                        //    edge.to.SecondValue = edge.weight + source.SecondValue;
                        //    edge.to.SecondPredecessor = AddToString(source.SecondPredecessor, edge.to.NodeName);
                        //}
                        //else if (edge.weight + source.SecondValue <= edge.to.ThirdValue)
                        //{
                        //    edge.to.ThirdValue = edge.weight + source.SecondValue;
                        //    edge.to.ThirdPredecessor = AddToString(source.SecondPredecessor, edge.to.NodeName);
                        //}

                        //if (edge.weight + source.ThirdValue <= edge.to.ThirdValue)
                        //{
                        //    edge.to.ThirdValue = edge.weight + source.ThirdValue;
                        //    edge.to.ThirdPredecessor = AddToString(source.ThirdPredecessor, edge.to.NodeName);
                        //}
                        #endregion

                    }

                }
                source.Mark = true;
                source = bestnode;
                bestnode = new GraphNode();
                bestnode.Value = double.PositiveInfinity;

            }
            completeRoute.BestAllDestinations = end.FirstPredecessor;
            completeRoute.BestTotalCost = end.Value;
            return completeRoute;

        }
        public string AddToString(string predecessor, string nextPredecessor)
        {
            if (predecessor == null)
            {
                return nextPredecessor;
            }
            else
            {
                return predecessor + " " + nextPredecessor;
            }
        }
    }

    public class CompleteRoute
    {
        public double BestTotalCost { get; set; }
        public string BestAllDestinations { get; set; }
        public double SecondTotalCost { get; set; }
        public string SecondAllDestinations { get; set; }
        public double ThirdTotalCost { get; set; }
        public string ThirdAllDestinations { get; set; }
    }
}
